package com.thunisoft.incremental.task;

import java.io.File;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import com.thunisoft.incremental.common.enums.TaskStatusEnum;
import com.thunisoft.incremental.common.model.Task;
import com.thunisoft.incremental.common.model.TaskStatus;
import com.thunisoft.incremental.common.util.DataBaseUtil;
import com.thunisoft.incremental.dao.TaskStatusMapper;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

/**
 * ExecuteManager
 *
 * @author Zhang Xin
 * @version v1.0
 * @since 2020/3/27 17:22
 */
@Component
@Slf4j
public class ExecuteManager {

    public static Map<String,TaskStatus> tasks = new ConcurrentHashMap<>();

    @Autowired
    private Execute execute;

    @Autowired
    private TaskStatusMapper taskStatusMapper;

    @Value("${copy.dir-path}")
    private String dataPath;

    @Async("taskExecutor")
    public void run(Task task, String groupId) {
        TaskStatus status = tasks.get(task.getId());
        if (status != null) {
            status.setDataPath(dataPath + task.getTablename()+".dat");
        } else {
            status = initStatus(groupId,task.getId(),dataPath + task.getTablename()+".dat");
        }
        try {
            status.setStatus(TaskStatusEnum.RUN.getCode());
            taskStatusMapper.updateByPrimaryKey(status);
            execute.manage(status,task);
            status.setStatus(TaskStatusEnum.SUCCESS.getCode());
            tasks.put(task.getId(),status);
        } catch (Exception e) {
            status.setEntime(new Date());
            status.setStatus(TaskStatusEnum.FAIL.getCode());
            log.error(e.getMessage(),e);
            status.setErrorLog(getStackTrace(e));
        } finally {
            tasks.remove(task.getId());
            taskStatusMapper.updateByPrimaryKey(status);
            File file = new File(status.getDataPath());
            if (file.isFile()) {
                file.delete();
            }
        }
    }

    public static TaskStatus initStatus(String groupId,String taskId,String dataPath){
        TaskStatus status = new TaskStatus();
        status.setId(DataBaseUtil.uuid());
        status.setStatus(TaskStatusEnum.WAIT.getCode());
        status.setStartTime(new Date());
        if (StringUtils.isNotBlank(groupId)) {
            status.setGroupId(groupId);
        }
        status.setTaskId(taskId);
        status.setDataPath(dataPath);
        return status;
    }

    @SneakyThrows
    public static String getStackTrace(Exception e){
        StringBuilder sb = new StringBuilder();
        sb.append(e.getMessage());
        sb.append("\r\n\r\n").append(e.toString());
        for (StackTraceElement stackTraceElement : e.getStackTrace()) {
            sb.append("\r\n\tat ").append(stackTraceElement);
        }
        sb.append("\r\nCaused by: ").append(e.getCause());
        for (StackTraceElement stackTraceElement : e.getCause().getStackTrace()) {
            sb.append("\r\n\tat ").append(stackTraceElement);
        }
        return sb.toString();

    }

}
